using System;
using System.Reflection;
using NUnitForVSTS.Common;

namespace NUnitForVSTS.NUnitHandling
{
    /// <summary>
    /// Utility class for handeling NUnit attributes.
    /// </summary>
	public static class MemberInfoExtentions
	{
        /// <summary>
        /// Attribute name of a Test fixture
        /// </summary>
		public const string TestFixtureAttributeType = "NUnit.Framework.TestFixtureAttribute";
        /// <summary>
        /// Attribute name of a setup
        /// </summary>
		public const string SetupAttributeType = "NUnit.Framework.SetUpAttribute";
        /// <summary>
        /// Attribute name of a Teardown
        /// </summary>
		public const string TeardownAttributeType = "NUnit.Framework.TearDownAttribute";
        /// <summary>
        /// Attribute name of a TestFixtureSetup
        /// </summary>
		public const string TestFixtureSetupAttributeType = "NUnit.Framework.TestFixtureSetUpAttribute";
        /// <summary>
        /// Attribute name of a TestFixture Teardown
        /// </summary>
		public const string TestFixtureTeardownAttributeType = "NUnit.Framework.TestFixtureTearDownAttribute";
        /// <summary>
        /// Attribute name of a Expected Exception
        /// </summary>
		public const string ExpectedExceptionAttributeType = "NUnit.Framework.ExpectedExceptionAttribute";

        /// <summary>
        /// Determines whether the specified type has attribute.
        /// </summary>
        /// <param name="type">The type.</param>
        /// <param name="attributeType">Type of the attribute.</param>
        /// <returns>
        /// 	<c>true</c> if the specified type has attribute; otherwise, <c>false</c>.
        /// </returns>
		public static bool HasAttribute(this MemberInfo type, string attributeType)
		{
			return HasAttribute(type, attributeType, true);
		}

        /// <summary>
        /// Determines whether the specified type has attribute.
        /// </summary>
        /// <param name="type">The type.</param>
        /// <param name="attributeType">Type of the attribute.</param>
        /// <param name="inherit">if set to <c>true</c> [inherit].</param>
        /// <returns>
        /// 	<c>true</c> if the specified type has attribute; otherwise, <c>false</c>.
        /// </returns>
		public static bool HasAttribute(this MemberInfo type, string attributeType, bool inherit)
		{
			Check.NotNull(type, "type");
			Check.NotNullOrEmpty(attributeType, "attributeType");

			return GetAttribute(type, attributeType, inherit) != null;
		}

        /// <summary>
        /// Gets the attribute.
        /// </summary>
        /// <param name="type">The type.</param>
        /// <param name="attributeType">Type of the attribute.</param>
        /// <returns></returns>
		public static Attribute GetAttribute(this MemberInfo type, string attributeType)
		{
			return GetAttribute(type, attributeType, true);
		}

        /// <summary>
        /// Gets the attribute.
        /// </summary>
        /// <param name="type">The type.</param>
        /// <param name="attributeType">Type of the attribute.</param>
        /// <param name="inherit">if set to <c>true</c> [inherit].</param>
        /// <returns></returns>
		public static Attribute GetAttribute(this MemberInfo type, string attributeType, bool inherit)
		{
			Check.NotNull(type, "type");
			Check.NotNullOrEmpty(attributeType, "attributeType");

			Attribute[] attributes = Attribute.GetCustomAttributes(type, inherit);
			foreach (Attribute attribute in attributes)
			{
				if (attribute.GetType().FullName.Equals(attributeType))
					return attribute;
			}
			return null;
		}
	}
}
